package com.robot.tools.service;

import com.alibaba.fastjson.JSON;
import entity.Sms;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author wuyunbin
 */
@Service
public class SmsService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${sys.scene}")
    private String sceneInYml;

    /**
     * 每天最多发送短信次数
     */
    @Value("${sys.sendSmsCount}")
    private int sysSendSmsCount;

    public boolean isCorrectScene(String flag) {
        return sceneInYml.contains(flag);
    }

    public boolean send(Sms sms) {
        int count = counter(sms);

        if (isTooMany(count)) {
            logger.info("sendSms:发送次数超过限制");
            return false;
        }
        //拼接存验证码的RedisKey
        String checkCodeRedisKey = getCheckCodeRedisKey(sms);
        //生成4位随机数
        String checkCode = RandomStringUtils.randomNumeric(4);

        sms.setCode(checkCode);
        //随机数存到Redis设置过期时间为10分钟
        redisTemplate.opsForValue().set(checkCodeRedisKey, checkCode, 10, TimeUnit.MINUTES);
        logger.info("send:phone=" + sms.getPhone() + " RedisKey=" + checkCodeRedisKey + " CheckCode=" + checkCode);
        //存一个到rabbitMq
        rabbitTemplate.convertAndSend("sms", JSON.toJSONString(sms));
        //拼接计数器的counterRedisKey
        String counterRedisKey = getCounterRedisKey(sms);
        redisTemplate.opsForValue().set(counterRedisKey, ++count);

        return true;

    }

    /**
     * 删除掉验证码
     * @param sms
     */
    public void deleteCheckCode(Sms sms) {
        //拼接场景RedisKey
        redisTemplate.delete(getCheckCodeRedisKey(sms));
        //拼接计数器RedisKey
        redisTemplate.delete(getCounterRedisKey(sms));
    }

    /**
     * 检查Redis里面的验证码是不是过期
     *
     * @param sms
     * @return
     */
    public boolean isCheckCodeExpire(Sms sms) {
        //拼接checkCodeRedisKey
        String checkCodeRedisKey = getCheckCodeRedisKey(sms);
        logger.info("isCheckCodeExpire:"+checkCodeRedisKey);
        if (!redisTemplate.hasKey(checkCodeRedisKey)) {
            return false;
        }
        return redisTemplate.getExpire(checkCodeRedisKey) > 0;
    }

    /**
     * 获取验证码的key
     *
     * @param sms
     * @return
     */
    private String getCheckCodeRedisKey(Sms sms) {
        return sms.getSender() + sms.getFlag() + sms.getPhone();
    }

    /**
     * 获取计数器的key
     *
     * @param sms
     * @return
     */
    private String getCounterRedisKey(Sms sms) {
        return sms.getSender() + sms.getFlag() + sms.getPhone() + "counter";
    }

    /**
     * 检查是否发送过多的短信
     *
     * @param count
     * @return
     */
    private boolean isTooMany(int count) {
        return count >= sysSendSmsCount;
    }

    /**
     * 短信计数
     *
     * @param sms
     * @return
     */
    private int counter(Sms sms) {
        //拼接counterRedisKey
        String counterRedisKey = getCounterRedisKey(sms);

        if (!redisTemplate.hasKey(counterRedisKey)) {
            redisTemplate.opsForValue().set(counterRedisKey, 0, 1, TimeUnit.DAYS);
            return 0;
        }
        Object obj = redisTemplate.opsForValue().get(counterRedisKey);
        return (int) obj;
    }

    public boolean isCorrectCheckCode(Sms sms, String checkCode) {
        //拼接checkCodeRedisKey
        String checkCodeRedisKey = getCheckCodeRedisKey(sms);
        logger.info("isCorrectCheckCode:"+checkCodeRedisKey);

        if (!redisTemplate.hasKey(checkCodeRedisKey)) {
            return false;
        }
        String checkCodeInRedis = redisTemplate.opsForValue().get(checkCodeRedisKey).toString();

        return checkCodeInRedis.equals(checkCode);
    }


}
